/*
 * @Description: 通用自定义指令
 * @Author: chenju
 * @Date: 2021-11-12 10:33:31
 * @LastEditors: chenju
 * @LastEditTime: 2022-08-19 10:12:26
 */
import type { App, DirectiveBinding } from 'vue';
import { limitStrLength } from '@/utils';

// 只输入数字
const numberOnly = {
  // When the bound element is mounted into the DOM...
  mounted(el: Element, binding: any) {
    const { value } = binding;
    console.log('numberOnly', value, binding);
    // const input: any = el;
    const input = el.getElementsByTagName('input')[0] || el;
    if (value && input) {
      input.onkeypress = (event: any) => {
        console.log(event.key, input.value);
        return /\d|\.|-/.test(event.key);
      };
    }
  }
};

// 只输入非负浮点数 小数点保留
const positiveOnly = {
  // v-positive-only:3 表示小数点后保留位数
  mounted(el: Element, binding: any) {
    // value用于在v-positive-only=”value“
    // arg指的是v-positive-only:3中的3
    const { value, arg } = binding;
    const limitLength = arg || value;
    const input = el.getElementsByTagName('input')[0];
    input.onkeypress = event => {
      console.log('onkeypress', event.key);
      // 无法屏蔽中文输入法等
      return /\d|\./.test(event.key);
    };
    input.onblur = () => {
      input.value = input.value.replace(/[^(0-9|.|\-)]/gi, '');
      input.value = limitStrLength(input.value, limitLength);
      // 调用input事件使vue v-model绑定更新
      input.dispatchEvent(new Event('input'));
    };
  }
};
// 只输入非负浮点数 小数点保留 input-number组件专用
const positiveOnlyInputNumber = {
  // v-positive-only:3 表示小数点后保留位数
  mounted(el: Element, binding: any) {
    const limitLength = binding.arg;
    const input = el.getElementsByTagName('input')[0];
    input.onkeypress = event => {
      console.log('onkeypress', event.key);
      // 无法屏蔽中文输入法等
      return /\d|\./.test(event.key);
    };
    input.onblur = () => {
      input.value = input.value.replace(/[^(0-9|.|\-)]/gi, '');
      input.value = limitStrLength(input.value, limitLength);
      // 调用input事件使vue v-model绑定更新
      input.dispatchEvent(new Event('input'));
      // 如果是el-input-number 需要同步触发change事件才能更新值
      input.dispatchEvent(new Event('change'));
    };
  }
};
//输入正负小数
const decimalOnly = {
  mounted(el: Element, binding: any) {
    const limitLength = binding.arg;
    const input = el.getElementsByTagName('input')[0];
    input.onkeypress = event => {
      console.log(event.key, /(^-)?\d|\./.test(event.key));
      return /\d|\.|-/.test(event.key);
    };
    input.onblur = () => {
      // 过滤除了0-9 . - 外所有字符
      input.value = input.value.replace(/[^(0-9|.|\-)]/gi, '');
      console.log('input.value', input.value);
      input.value = limitStrLength(input.value, limitLength, true);
      // 调用input事件使vue v-model绑定更新
      input.dispatchEvent(new Event('input'));
    };
  }
};

// 输入正负小数 其中blur的触发事件的时机在vue的@blur之前
// NOTE 利用的是事件捕获的原理
const decimalOnlyBefore = {
  mounted(el: Element, binding: any) {
    const limitLength = binding.arg;
    const input = el.getElementsByTagName('input')[0];
    console.log('decimalTestOnly bind');
    input.addEventListener(
      'keypress',
      (event: any) => {
        console.log(event.key, /(^-)?\d|\./.test(event.key));
        return /\d|\.|-/.test(event.key);
      },
      true
    );
    input.addEventListener(
      'blur',
      () => {
        console.log('decimalTestOnly blur');
        // 过滤除了0-9 . - 外所有字符
        input.value = input.value.replace(/[^(0-9|.|\-)]/gi, '');
        console.log('input.value', input.value);
        input.value = limitStrLength(input.value, limitLength, true);
        // 调用input事件使vue v-model绑定更新
        input.dispatchEvent(new Event('input'));
      },
      true
    );
  }
};

// 只输入非负浮点数 小数点保留 适用于input v-model.lazy的形式
const inputPositiveOnly = {
  // v-positive-only:3 表示小数点后保留位数
  // When the bound element is mounted into the DOM...
  mounted(el: any, binding: any) {
    const limitLength = binding.arg;
    const input = el;
    input.onkeypress = (event: any) => {
      return /\d|\./.test(event.key);
    };
    input.onblur = () => {
      input.value = input.value.replace(/[^(0-9|.|\-)]/gi, '');
      input.value = limitStrLength(input.value, limitLength);
      // 调用input事件使vue v-model绑定更新
      input.dispatchEvent(new Event('change'));
    };
  }
};

type NumberValidParams = number | NumberValidLimitParams;

interface NumberValidLimitParams {
  digit?: number;
  canNegative?: boolean;
}

// 输入数字校验，支持配置
const numberValid = {
  mounted(el: Element, binding: DirectiveBinding<NumberValidParams>) {
    const { value, arg } = binding;
    // 保留小数位数，默认0
    let digit: number = arg ? 0 : Number(arg);
    // 是否可以为负数
    let canNegative = false;
    if (typeof value === 'number') {
      digit = value;
    } else if (value && typeof value === 'object') {
      digit = value.digit || 0;
      canNegative = value.canNegative || false;
    }
    // el-input内获取input元素
    let input = el.getElementsByTagName('input')[0];
    if (!input) {
      // 普通input元素
      input = el as HTMLInputElement;
    }
    input.onkeypress = event => {
      if (canNegative) {
        return /\d|\.|-/.test(event.key);
      }
      return /\d|\./.test(event.key);
    };
    input.onblur = () => {
      if (canNegative) {
        // 过滤除了0-9 . - 外所有字符
        input.value = input.value.replace(/[^(0-9|.|\-)]/gi, '');
      } else {
        // 过滤除了0-9 . 外所有字符
        input.value = input.value.replace(/[^(0-9|.)]/gi, '');
      }
      input.value = limitStrLength(input.value, digit, canNegative);
      // 调用input事件使vue v-model绑定更新
      input.dispatchEvent(new Event('input'));
    };
  }
};

export function setupCommonDirectives(app: App): void {
  app.directive('numberOnly', numberOnly);
  app.directive('positiveOnly', positiveOnly);
  app.directive('positiveOnlyInputNumber', positiveOnlyInputNumber);
  app.directive('decimalOnly', decimalOnly);
  app.directive('decimalOnlyBefore', decimalOnlyBefore);
  app.directive('inputPositiveOnly', inputPositiveOnly);
  app.directive('numberValid', numberValid);
}
